package tenglang.common.jackson;

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

/**
 * jackson 工具类，用来转换json对象和java实体
* @ClassName: BeanUtils 
* @Description: TODO(jackson 工具类，用来转换json对象和java实体 ) 
* @author wangjun
* @date 2018年5月7日 下午2:50:17 
 */
public class BeanUtils extends org.springframework.beans.BeanUtils{
	
	/**
	 * 将java对象转化为json字符串，转化对象包含javaBean,List,Map以及基础类型和包装类型
	 * 
	* @Title: convertJavaBeanToString 
	* @Description: TODO(jackson 工具类，用来转换json对象和java实体) 
	* @param  obj  被转化的对象
	* @param @return
	* @param @throws Exception    设定文件 
	* @return String    转化后的json字符串 
	* @author wangjun
	* @throws
	 */
	public static String convertJavaBeanToString(Object obj) throws Exception{
		   return getObjectMapper().writeValueAsString(obj);
	}
	
	/**
	 * 将json字符串转化为List集合
	* @Title: converToListFromJsonNode 
	* @Description: TODO(将json字符串转化为List集合) 
	* @param @param source  json字符串
	* @param @param valueType 集合元素的类型
	* @param @return
	* @param @throws Exception    设定文件 
	* @return List<T>    返回类型 
	* @author wangjun
	* @throws
	 */
	public static <T> List<T>  converToListFromJsonNode(String source,Class<T> valueType) throws Exception{
		  ObjectMapper objectMapper=getObjectMapper();
		  JavaType javaType =objectMapper.getTypeFactory().constructCollectionType(List.class, valueType);
		  return objectMapper.readValue(source, javaType);
	}
	
	
	/**
	 * 将json字符串转化为数组
	* @Title: converToArrayFromJsonNode 
	* @Description: TODO(将json字符串转化为数组) 
	* @param @param source json字符串
	* @param @param valueType  数组元素的类型
	* @param @return
	* @param @throws Exception    设定文件 
	* @return Array    返回类型 
	* @throws
	 */
	public static <T> Array  converToArrayFromJsonNode(String source,Class<T> valueType) throws Exception{
		 ObjectMapper objectMapper=getObjectMapper();
		 JavaType javaType = objectMapper.getTypeFactory().constructArrayType(valueType);
		 return objectMapper.readValue(source, javaType);
	}
	
	
	/**
	 * 将json字符串转化为Map<String,T>的HashMap
	* @Title: converToMapFromJsonNode 
	* @Description: TODO(将json字符串转化为Map<String,T>的HashMap) 
	* @param @param source  json字符串 
	* @param @param valueType  map值的数据类型
	* @param @return
	* @param @throws Exception    设定文件 
	* @return Map<String,T>    返回类型 
	* @throws
	 */
	public static <T> Map<String,T> converToMapFromJsonNode(String source,Class<T> valueType)throws Exception{
		ObjectMapper objectMapper=getObjectMapper();
		JavaType javaType =objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, valueType);
		return objectMapper.readValue(source, javaType);
	}
	
	
	/**
	 * 将json数据流转化为Map<String,T>的HashMap
	* @Title: converToMapFromJsonNode 
	* @Description: TODO(将json字符串转化为Map<String,T>的HashMap) 
	* @param @param source  json字符串 
	* @param @param valueType  map值的数据类型
	* @param @return
	* @param @throws Exception    设定文件 
	* @return Map<String,T>    返回类型 
	* @throws
	 */
	public static <T> Map<String,T> converToMapFromJsonNode(InputStream source,Class<T> valueType)throws Exception{
		ObjectMapper objectMapper=getObjectMapper();
		JavaType javaType =objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, valueType);
		return objectMapper.readValue(source, javaType);
	}
	
	
	public static <T> List<Map<String,T>> converToListMapFromJsonNode(String source,Class<T> valueType)throws Exception{
		ObjectMapper objectMapper=getObjectMapper();
		JavaType javaType =objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, valueType);
		JavaType listType= objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, javaType);
		return objectMapper.readValue(source, listType);
	}
	
	
	/**
	 * 将json数组对象转化为List
	* @Title: converToListFromJsonNode 
	* @Description: TODO(将json数组对象转化为List) 
	* @param @param arrayNode
	* @param @param valueType 集合元素类型
	* @param @return
	* @param @throws Exception    设定文件 
	* @return List<T>    返回类型 
	* @throws
	 */
	public static <T> List<T>  converToListFromJsonNode(ArrayNode arrayNode,Class<T> valueType) throws Exception{
		ObjectMapper objectMapper=getObjectMapper();
		 JavaType javaType =objectMapper.getTypeFactory().constructCollectionType(List.class, valueType);
		return objectMapper.readValue(arrayNode.traverse(), javaType);
	}
	
	
	/**
	 *   将对象转换为JsonNode对象
	 */
	public static JsonNode writeValueTree(Object obj) {
		ObjectMapper objectMapper=getObjectMapper();
		return objectMapper.valueToTree(obj);
	}
	
	
	/**
	 * 
	 * @param obj
	 * @param properties
	 * @return
	 */
	public static JsonNode writeValueTree(Object obj,String... properties) {
		ObjectMapper objectMapper=getObjectMapper();
		filter(objectMapper, obj.getClass().getName(), properties);
		return objectMapper.valueToTree(obj);
	}
	
	
	
	/**
	 * 构造一个新的JsonObject对象
	* @Title: createObjectNode 
	* @Description: TODO(构造一个新的JsonObject对象) 
	* @param @return    设定文件 
	* @return ObjectNode    返回类型 
	* @author wangjun
	* @throws
	 */
	public static ObjectNode createObjectNode(){
		ObjectMapper objectMapper=getObjectMapper();
		return objectMapper.createObjectNode();
	}
	
	
	/**
	 * 构造一个新的JsonObject对象
	* @Title: createArrayNode 
	* @Description: TODO(构造一个新的JsonObject对象) 
	* @param @return    设定文件 
	* @return ObjectNode  返回类型 
	* @author wangjun
	* @throws
	 */
	public static ArrayNode createArrayNode(){
		ObjectMapper objectMapper=getObjectMapper();
		return objectMapper.createArrayNode();
	}
	
	
	/**
	 * 定制格式化工厂类
	* @Title: getObjectMapper 
	* @Description: TODO(定制格式化工厂类) 
	* @param @return    设定文件 
	* @return ObjectMapper    返回类型 
	* @author wangjun
	* @throws
	 */
	public static ObjectMapper getObjectMapper(){
		ObjectMapper objectMapper= new ObjectMapper();
		objectMapper.configure(Feature.ALLOW_COMMENTS, true);
		objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true) ;
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(Feature.IGNORE_UNDEFINED, true);
        
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性  
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        objectMapper.setSerializationInclusion(Include.NON_NULL);  
        
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-mm-dd HH:mm:ss"));
	    
	    SimpleModule module = new SimpleModule(); 
	    module.addDeserializer(Date.class,new UTCDateDeserializer());
	    module.addSerializer(Date.class, new UTCDateSerializer());
	    objectMapper.registerModule(module);
		return objectMapper;
	}
	
	
	/**
	 * 定制格式化工厂类
	* @Title: getObjectMapper 
	* @Description: TODO(定制格式化工厂类) 
	* @param @return    设定文件 
	* @return ObjectMapper    返回类型 
	* @author wangjun
	* @throws
	 */
	public static ObjectMapper getObjectMapper(String filterName,String[] beanProperties){
		ObjectMapper objectMapper= new ObjectMapper();
		objectMapper.configure(Feature.ALLOW_COMMENTS, true);
		objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true) ;
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(Feature.IGNORE_UNDEFINED, true);
        
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性  
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        objectMapper.setSerializationInclusion(Include.NON_NULL);  
	    
        FilterProvider filterProvider = new SimpleFilterProvider()
                .addFilter(filterName, SimpleBeanPropertyFilter.serializeAllExcept(beanProperties)); 
        objectMapper.setFilterProvider(filterProvider);

	    SimpleModule module = new SimpleModule(); 
	    module.addDeserializer(Date.class,new UTCDateDeserializer());
	    module.addSerializer(Date.class, new UTCDateSerializer());
	    objectMapper.registerModule(module);
		return objectMapper;
	}
	
	 /**
	  * serializeAllExcept 表示序列化全部，除了指定字段                
	  * filterOutAllExcept 表示过滤掉全部，除了指定的字段
	  * @param objectMapper
	  * @param filterName
	  * @param properties
	  */
	public static void filter(ObjectMapper objectMapper,String filterName, String... properties) {  
        FilterProvider filterProvider = new SimpleFilterProvider().addFilter(filterName,  
         SimpleBeanPropertyFilter.serializeAllExcept(properties));  
        objectMapper.setFilterProvider(filterProvider);
    } 
	
	
	
	public static JsonNode readTreeFromContent(Object content) throws Exception{
		 ObjectMapper objectMapper=getObjectMapper();
		 JsonNode jsonNode=null;
		 if(InputStream.class.isInstance(content)) {
			 jsonNode=objectMapper.readTree((InputStream)content);
		 }else if(Reader.class.isInstance(content)) {
			 jsonNode=objectMapper.readTree((Reader)content);
		 }else if(String.class.isInstance(content)) {
			 jsonNode=objectMapper.readTree((String)content);
		 }else if(File.class.isInstance(content)) {
			 jsonNode=objectMapper.readTree((File)content);
		 }
		 return jsonNode;
	}
    
	/**
	 * 简单的json表达式与Map的转化，支持基本类型的转化
	 * 转化方式为{
	 *    "int_name|I"："2", 传入int类型
	 *    "boolean_name|B"："2", 传入boolean类型
	 *    "boolean_name|D"："2", 传入double类型
	 * }
	* @Title: getMapByExpressionStr 
	* @Description: TODO(通过字符表达是获取) 
	* @param @param expressionStr
	* @param @return    设定文件 
	* @return Map<String,Object>    返回类型 
	* @throws
	 */
	public static Map<String, Object> getMapByExpressionJsonStr(String expressionStr){
		ObjectMapper objectMapper= new ObjectMapper();
		objectMapper.configure(Feature.ALLOW_COMMENTS, true);
		objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true) ;
        objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(Feature.IGNORE_UNDEFINED, true);
        
        Map<String,Object> expressionMap=new HashMap();
        if(StringUtils.isNotBlank(expressionStr)) {
        	try {
        	   JsonNode jsonNode=objectMapper.readTree(expressionStr);
        	   if(jsonNode.isObject()) {
        		    ObjectNode objectNode=(ObjectNode)jsonNode;
        		    Iterator<Entry<String, JsonNode>> fieldsIterator=objectNode.fields();
        		    while(fieldsIterator.hasNext()) {
        		    	Entry<String, JsonNode> fieldsEntry=fieldsIterator.next();
        		    	if(fieldsEntry.getKey().indexOf("|")>-1) {
        		    		if(fieldsEntry.getKey().split("\\|", 2)[1].equals("I")) {
        		    			expressionMap.put(fieldsEntry.getKey().split("\\|", 2)[0], fieldsEntry.getValue().asInt());
        		    		}else if(fieldsEntry.getKey().split("\\|", 2)[1].equals("B")) {
        		    			expressionMap.put(fieldsEntry.getKey().split("\\|", 2)[0], fieldsEntry.getValue().asBoolean());
        		    		}else if(fieldsEntry.getKey().split("\\|", 2)[1].equals("L")) {
        		    			expressionMap.put(fieldsEntry.getKey().split("\\|", 2)[0], fieldsEntry.getValue().asLong());
        		    		}else if(fieldsEntry.getKey().split("\\|", 2)[1].equals("D")) {
        		    			expressionMap.put(fieldsEntry.getKey().split("\\|", 2)[0], fieldsEntry.getValue().asDouble());
        		    		}else if(fieldsEntry.getKey().split("\\|", 2)[1].equals("T")){
        		    			expressionMap.put(fieldsEntry.getKey().split("\\|", 2)[0], new Date(fieldsEntry.getValue().asLong()));
        		    		}else if(fieldsEntry.getKey().split("\\|", 2)[1].equals("S")) {
        		    			expressionMap.put(fieldsEntry.getKey().split("\\|", 2)[0], fieldsEntry.getValue().asText());
        		    		}
        		    	}else {
        		    		expressionMap.put(fieldsEntry.getKey(), fieldsEntry.getValue().asText());
        		    	}
        		    }
        	   }
        	}catch(Exception e) {
        		 e.printStackTrace();
        	}
        }
		return expressionMap;
	}
	
	
	
	public static Map<String, Object> getMapBySpecStr(String expressionStr){
		String[] fieldValuesArr=expressionStr.split(";");
        Map<String,Object> expressionMap=new HashMap();
		for(String fieldValueItem:fieldValuesArr) {
			String fieldKey=fieldValueItem.split("=", 2)[0];
			String fieldValue=fieldValueItem.split("=", 2)[1];
			if(fieldKey.indexOf("|")>-1) {
	    		if(fieldKey.split("\\|", 2)[1].equals("I")) {
	    			expressionMap.put(fieldKey.split("\\|", 2)[0], new Integer(fieldValue));
	    		}else if(fieldKey.split("\\|", 2)[1].equals("B")) {
	    			expressionMap.put(fieldKey.split("\\|", 2)[0], new Boolean(fieldValue));
	    		}else if(fieldKey.split("\\|", 2)[1].equals("L")) {
	    			expressionMap.put(fieldKey.split("\\|", 2)[0], new Long(fieldValue));
	    		}else if(fieldKey.split("\\|", 2)[1].equals("D")) {
	    			expressionMap.put(fieldKey.split("\\|", 2)[0], new Double(fieldValue));
	    		}else if(fieldKey.split("\\|", 2)[1].equals("T")){
	    			expressionMap.put(fieldKey.split("\\|", 2)[0], new Date(Long.parseLong(fieldValue)));
	    		}else if(fieldKey.split("\\|", 2)[1].equals("S")) {
	    			expressionMap.put(fieldKey.split("\\|", 2)[0], fieldValue);
	    		}
	    	}else {
	    		expressionMap.put(fieldKey, fieldValue);
	    	}
		}
		return expressionMap;
	}
	
	
	/**
	 * 获取对象值
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	public static Object getValueByName(Object obj, String fieldName){
	    String Upper;
	    String methodStr;
	    Method method;
	    Object o;
	    try{
	      fieldName = fieldName.trim();
	      fieldName = fieldName.toLowerCase();
			//下划线处理，不考虑下划线是最后一位的情况
			int index = -1;
			while((index = fieldName.indexOf("_")) > -1){
				Upper = fieldName.substring(index+1, index+2).toUpperCase();
				fieldName = fieldName.substring(0, index) + Upper + fieldName.substring(index+2);
			}
	      
	      Upper = fieldName.substring(0, 1).toUpperCase();
	      methodStr = "get" + Upper + fieldName.substring(1);
	      method = obj.getClass().getMethod(methodStr, new Class[0]);

	      o = method.invoke(obj, new Object[0]);
	      if(Enum.class.isInstance(o)) {
	    	  Enum enumR=(Enum)o;
	    	  return enumR.ordinal();
	      }else {
	    	  return o;
	      }
	    } catch (Exception e) {
	      methodStr = "get" + fieldName;
	      try
	      {
	        method = obj.getClass().getMethod(methodStr, new Class[0]);
	        o = method.invoke(obj, new Object[0]);
	        return o; } catch (Exception e1) {
	      }
	    }
	    return null;
	 }
	
	/**
	 * 获取插入语句需插入的字段
	 * @param sql
	 * @return
	 */
	public static String[] getInsertSqlFields(String sql) {
		String insert = sql.substring(sql.indexOf("(")+1, sql.indexOf(")"));
		String[] insertFields = insert.split(",");
		return insertFields;
	}
	
	public static Object[] getArrayByFields(Object obj,String[] fields) {
		  Object[] objs=new Object[fields.length];
		  int idx=0;
		  for(String s:fields) {
			  try {
			    objs[idx++]=BeanUtils.getValueByName(obj, s);
			  }catch (Exception e) {
				  objs[idx++]=null;
			}
		  }
		  return objs;
		   
	}
	
	/**
	 * 获取更新语句需插入的字段
	 * @param sql
	 * @return
	 */
	public static String[] getUpdateSqlFields(String sql) {
		String update = sql.substring(sql.indexOf("set")+4, sql.indexOf("where"));
		String update2 = sql.substring(sql.indexOf("where")+6);
		update += ","+update2.replaceAll("and", ",");
		String[] updateFields = update.split(",");
		return updateFields;
	}
	
	public static String uuid() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}
	
     public static boolean isNumber(String src) {
    	 boolean strResult = src.matches("-?[0-9]+.*[0-9]*");    
    	 return strResult;
     }
	
	
	public static Timestamp timestamp() {
		 return new Timestamp(System.currentTimeMillis());
	}
	
	public static void main(String[] args) {
		System.out.println(NumberUtils.isNumber("12.5"));
		/* String s="workTime|I=0;taskStartTime|T=1543661700888;taskKey|S=1002;failNum|I=0";
		 Map<String, Object> field=getMapBySpecStr(s);
		 Iterator<Entry<String, Object>> fields=field.entrySet().iterator();
		 while(fields.hasNext()) {
			 Entry<String, Object> entry=fields.next();
			 System.out.println(entry.getKey()+"#"+entry.getValue());
		 }*/
	}
}
